<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>场景设定 | vform-element</title>
    <meta name="description" content="基于 Vue3 和 Element-plus 的动态表单组件">
    <link rel="stylesheet" href="/vform-element/assets/style.d788119a.css">
    <link rel="modulepreload" href="/vform-element/assets/chunks/framework.63bebe7e.js">
    <link rel="modulepreload" href="/vform-element/assets/chunks/_commonjsHelpers.ba691886.js">
    <link rel="modulepreload" href="/vform-element/assets/chunks/chat-round.0845d834.js">
    <link rel="modulepreload" href="/vform-element/assets/chunks/config-provider2.da89bd12.js">
    <link rel="modulepreload" href="/vform-element/assets/chunks/builder.040a1dc4.js">
    <link rel="modulepreload" href="/vform-element/assets/guide_why.md.1126621f.lean.js">
    <link rel="modulepreload" href="/vform-element/assets/app.361feb9c.js">
    
    <meta name="twitter:title" content="场景设定 | vform-element">
  <meta property="og:title" content="场景设定 | vform-element">
  </head>
  <body>
    <div id="app"><!--[--><!--[--><div class="theme"><header class="nav-bar" data-v-29dab36d><div class="nav-bar-wrapper" data-v-29dab36d><div class="sidebar-button" data-v-29dab36d><svg class="icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z" class></path></svg></div><a class="nav-bar-title" href="/vform-element/" aria-label="vform-element, back to home" data-v-29dab36d data-v-fcdf2a90><!----> vform-element</a><div class="flex-grow" data-v-29dab36d></div><div class="nav" data-v-29dab36d><nav class="nav-links" data-v-29dab36d data-v-68d46b9e><!--[--><div class="item" data-v-68d46b9e><div class="nav-link" data-v-68d46b9e data-v-7e0eb2fd><a class="item" href="/vform-element/" data-v-7e0eb2fd>首页 <!----></a></div></div><div class="item" data-v-68d46b9e><div class="nav-link" data-v-68d46b9e data-v-7e0eb2fd><a class="item active" href="/vform-element/guide/get-start.html" data-v-7e0eb2fd>指南 <!----></a></div></div><div class="item" data-v-68d46b9e><div class="nav-link" data-v-68d46b9e data-v-7e0eb2fd><a class="item" href="/vform-element/api/form.html" data-v-7e0eb2fd>配置 <!----></a></div></div><div class="item" data-v-68d46b9e><div class="nav-link" data-v-68d46b9e data-v-7e0eb2fd><a class="item isExternal" href="https://github.com/foolishchow/vform" target="_blank" rel="noopener noreferrer" data-v-7e0eb2fd>Github <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-7e0eb2fd><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><!--]--><!----><!----></nav></div><!--[--><!--]--></div></header><aside class="sidebar" data-v-018e9cb6><nav class="nav-links nav" data-v-018e9cb6 data-v-68d46b9e><!--[--><div class="item" data-v-68d46b9e><div class="nav-link" data-v-68d46b9e data-v-7e0eb2fd><a class="item" href="/vform-element/" data-v-7e0eb2fd>首页 <!----></a></div></div><div class="item" data-v-68d46b9e><div class="nav-link" data-v-68d46b9e data-v-7e0eb2fd><a class="item active" href="/vform-element/guide/get-start.html" data-v-7e0eb2fd>指南 <!----></a></div></div><div class="item" data-v-68d46b9e><div class="nav-link" data-v-68d46b9e data-v-7e0eb2fd><a class="item" href="/vform-element/api/form.html" data-v-7e0eb2fd>配置 <!----></a></div></div><div class="item" data-v-68d46b9e><div class="nav-link" data-v-68d46b9e data-v-7e0eb2fd><a class="item isExternal" href="https://github.com/foolishchow/vform" target="_blank" rel="noopener noreferrer" data-v-7e0eb2fd>Github <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-7e0eb2fd><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><!--]--><!----><!----></nav><!--[--><!--]--><ul class="sidebar-links" data-v-018e9cb6><!--[--><li class="sidebar-link"><a class="sidebar-link-item active" href="/vform-element/guide/why.html">为什么</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/vform-element/guide/get-start.html">开始使用</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/vform-element/guide/custom-render.html">拓展性</a><!----></li><!--]--></ul><!--[--><!--]--></aside><div class="sidebar-mask"></div><main class="page" data-v-7b60a085><div class="page-left" data-v-7b60a085></div><div class="container" data-v-7b60a085><!--[--><!--]--><div style="position:relative;" class="content" data-v-7b60a085><div><div class="warning custom-block"><p class="custom-block-title">问题</p><p>前端的轮子千千万，已经有 <code>element-plus</code> 了， 为何还要造轮子？</p></div><div class="tip custom-block"><p class="custom-block-title">TIP</p><p>通过一个具体场景，解释为什么要使用动态表单</p></div><h2 id="场景设定" tabindex="-1">场景设定 <a class="header-anchor" href="#场景设定" aria-hidden="true">#</a></h2><p>假设我们有一个场景，需要录入用户的<code>姓名</code>、<code>性别</code>、<code>生日</code>这几个数据，其中</p><ul><li>所有数据都必填</li><li>性别选项要冲后台异步获取</li><li>生日要获取 时间戳(精确到秒)</li></ul><h2 id="不使用vform-element" tabindex="-1">不使用<code>vform-element</code> <a class="header-anchor" href="#不使用vform-element" aria-hidden="true">#</a></h2><p>看一下常见的表单开发流程,这个例子有两个注意点</p><ul><li><code>brithday</code> 后台需要的是 <code>时间戳</code> , 需要做转换, 所以把 <code>brithday</code> 做成 <code>computed</code></li><li><code>性别</code> 选项是一个异步获取的选项，使用 <code>ref</code> 实现动态绑定</li></ul><!----><div class="info custom-block"><p class="custom-block-title">总结</p><p>上面的例子中，我们可以发现</p><ul><li><code>formData</code> , <code>Rules</code> 是上下文的核心, 配置 Form 以及每个 FormItem 的时候都会用到</li><li><code>FormItem</code> 的 <code>prop</code> 属性和 <code>Item</code> 子项的 <code>v-model:xxx</code> 属性其实都可以用 <code>formData[Key]</code> 来统一</li><li>像 <code>select</code> 这种异步获取选项的，我们需要为 <code>Select</code> 创建 <code>ref</code> 实现数据双向绑定</li><li><code>birthday</code>这种需要 转换数据的操作 ，则还需要单独定义<code>ref</code></li><li>我们会在<code>setup</code>中定义许多变量来实现类似<code>异步数据绑定</code>、<code>数据转换</code>等操作，并在后面的页面渲染中根据配置使用他们，</li></ul><blockquote><p>由此可以发现，在开发过程中，我们一直在 script 与 template/jsx 间上下文切换</p></blockquote><p>总体来看，我们为了业务的实现，定义了很多分散的业务处理，并需要在单独的指定到我们的渲染上</p></div><h2 id="动态配置" tabindex="-1">动态配置 <a class="header-anchor" href="#动态配置" aria-hidden="true">#</a></h2><!----><div class="info custom-block"><p class="custom-block-title">总结</p><ul><li><h4 id="普通配置（姓名）" tabindex="-1">普通配置（姓名） <a class="header-anchor" href="#普通配置（姓名）" aria-hidden="true">#</a></h4><ul><li>对于普通的配置，我们将 <code>label</code>、<code>prop</code>、<code>v-model</code>、<code>rule</code> 集中到一起配置了</li><li>每个类型的表单元素，添加了<code>props</code>配置项来实现</li></ul></li><li><h4 id="数据转换（生日brithday）" tabindex="-1">数据转换（生日brithday） <a class="header-anchor" href="#数据转换（生日brithday）" aria-hidden="true">#</a></h4><ul><li>需要进行数据转换的表单元素，添加了<code>transfer</code>配置项来实现</li></ul></li><li><h4 id="异步数据绑定" tabindex="-1">异步数据绑定 <a class="header-anchor" href="#异步数据绑定" aria-hidden="true">#</a></h4><ul><li>异步数据绑定，我们可以使用<code>Function</code>配置表单元素</li></ul></li></ul><div class="language-typescript line-numbers-mode"><pre><code><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=&gt;</span><span class="token punctuation">{</span> <span class="token comment">//定义性别这个选项是一个Function</span>
  <span class="token keyword">const</span> SexOpt <span class="token operator">=</span> <span class="token generic-function"><span class="token function">ref</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token punctuation">{</span> label<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> value<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token punctuation">}</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
  <span class="token function">getSexOpt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>opt <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    SexOpt<span class="token punctuation">.</span>value <span class="token operator">=</span> opt
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    label<span class="token operator">:</span> <span class="token string">&quot;性别&quot;</span><span class="token punctuation">,</span>
    dataIndex<span class="token operator">:</span> <span class="token string">&quot;sex&quot;</span><span class="token punctuation">,</span>
    <span class="token function-variable function">option</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> SexOpt<span class="token punctuation">.</span>value<span class="token punctuation">,</span>
    props<span class="token operator">:</span> <span class="token punctuation">{</span>
      placeholder<span class="token operator">:</span> <span class="token string">&quot;请选择性别&quot;</span><span class="token punctuation">,</span>
      clearable<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    rule<span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token punctuation">{</span> required<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> message<span class="token operator">:</span> <span class="token string">&#39;请选择性别&#39;</span> <span class="token punctuation">}</span>
    <span class="token punctuation">]</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div></div></div></div><footer class="page-footer" data-v-7b60a085 data-v-4b340945><div class="edit" data-v-4b340945><div class="edit-link" data-v-4b340945 data-v-b84fa0d0><!----></div></div><div class="updated" data-v-4b340945><!----></div></footer><div class="next-and-prev-link" data-v-7b60a085 data-v-6851b17c><div class="container" data-v-6851b17c><div class="prev" data-v-6851b17c><!----></div><div class="next" data-v-6851b17c><a class="link" href="/vform-element/guide/get-start" data-v-6851b17c><span class="text" data-v-6851b17c>开始使用</span><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon icon-next" data-v-6851b17c><path d="M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z"></path></svg></a></div></div></div><!--[--><!--]--></div><!----></main></div><!----><!--]--><!--]--></div>
    <script>__VP_HASH_MAP__ = JSON.parse("{\"api_autocomplete.md\":\"d38ba630\",\"api_cascader.md\":\"19457b39\",\"api_checkbox-group.md\":\"aa4f1ba9\",\"api_color-picker.md\":\"5b629c8a\",\"api_date-picker.md\":\"88da5445\",\"api_date-time-picker.md\":\"0697ffae\",\"api_form-item.md\":\"976bc258\",\"api_form.md\":\"ea45ab81\",\"api_input-number.md\":\"a1c0ffe4\",\"api_input.md\":\"36121401\",\"api_radio-group.md\":\"4d20f5c2\",\"api_rate.md\":\"ac385ba6\",\"api_select-v2.md\":\"1454d42a\",\"api_select.md\":\"7cc174f5\",\"api_slider.md\":\"c13c55ce\",\"api_switch.md\":\"eda4ad4d\",\"api_time-picker.md\":\"c9d01cac\",\"api_time-select.md\":\"81635e6f\",\"api_transfer.md\":\"73f5a58d\",\"api_upload.md\":\"3f1d8a0e\",\"guide_custom-render.md\":\"5f5a4fde\",\"guide_get-start.md\":\"1c5502f9\",\"guide_how.md\":\"62e7e9ca\",\"guide_why.md\":\"1126621f\",\"index.md\":\"cfdf7747\"}")</script>
    <script type="module" async src="/vform-element/assets/app.361feb9c.js"></script>
    
  </body>
</html>